package config

import (
	"fmt"
	"strings"

	"github.com/fsnotify/fsnotify"
	"github.com/i582/cfmt/cmd/cfmt"
	"github.com/spf13/viper"
	_ "github.com/spf13/viper/remote"
	"go.uber.org/zap"
)

var Conf = new(ServerConfig)

// Config 配置结构体

type Config struct {
	Server  ServerConfig
	MySQL   MySQLParams
	Redis   RedisParams
	Log     LogParams
	Minio   MinioParams
	WeChat  WeChatOAuth2Config
	Tencent TencentOAuth2Config
	// Casbin  CasbinConfig
}

// ServerConfig 全局配置信息
type ServerConfig struct {
	Version             string              `mapstructure:"version"`     // 配置文件版本
	AppName             string              `mapstructure:"app_name"`    // 程序名称
	Port                int                 `mapstructure:"server_port"` // 运行端口
	Mode                string              `mapstructure:"run_mode"`    // 运行模式
	MySQLConfig         MySQLParams         `mapstructure:"mysql"`
	RedisConfig         RedisParams         `mapstructure:"redis"`
	LogConfig           LogParams           `mapstructure:"log_config"`
	MinioConfig         MinioParams         `mapstructure:"minio"`
	WeChatOAuth2Config  WeChatOAuth2Config  `mapstructure:"wechat_oauth2_config"`
	TencentOAuth2Config TencentOAuth2Config `mapstructure:"tencent_oauth2_config"`
}

// LogParams 日志全局配置
type LogParams struct {
	Level      string `mapstructure:"level"`       // 日志等级
	MaxSize    int    `mapstructure:"max_size"`    // 日志大小: 单位M
	MaxAge     int    `mapstructure:"max_age"`     // 日志存放时间: 单位天
	MaxBackups int    `mapstructure:"max_backups"` // 最大备份数量
	Compress   bool   `mapstructure:"compress"`    // 是否压缩日志
	Filename   string `mapstructure:"filename"`    // 日志文件名称
	Format     string `mapstructure:"format"`      // 日志格式
}

// RedisParams Redis配置
type RedisParams struct {
	Address  string `mapstructure:"address"`  // Redis地址
	DB       int    `mapstructure:"db"`       // 数据库编号
	Password string `mapstructure:"password"` // 密码
}

// MySQLParams MySQL配置
type MySQLParams struct {
	User      string `mapstructure:"user"`       // 数据库用户名
	Host      string `mapstructure:"host"`       // 数据库地址
	Port      string `mapstructure:"port"`       // 数据库端口
	Password  string `mapstructure:"password"`   // 数据库密码
	Database  string `mapstructure:"database"`   // 数据库名
	Charset   string `mapstructure:"charset"`    // 字符集
	ParseTime bool   `mapstructure:"parse_time"` // 是否解析时间
	LogLevel  string `mapstructure:"log_level"`  // 日志级别
}

// MinioParams Minio配置
type MinioParams struct {
	Server          string `mapstructure:"server"`            // MinIO服务器地址
	Domain          string `mapstructure:"domain"`            // MinIO域名
	AccessKey       string `mapstructure:"access_key"`        // AccessKey
	SecretAccessKey string `mapstructure:"secret_access_key"` // SecretAccessKey
}

// WeChatOAuth2Config 微信SSO配置
type WeChatOAuth2Config struct {
	AppID  string `mapstructure:"app_id"` // 微信AppID
	Secret string `mapstructure:"secret"` // 微信Secret
}

// TencentOAuth2Config 腾讯SSO配置
type TencentOAuth2Config struct {
	AppID  string `mapstructure:"app_id"`  // 腾讯AppID
	AppKey string `mapstructure:"app_key"` // 腾讯AppKey
}

// type CasbinConfig struct {
// 	ModelPath string `mapstructure:"model-path" json:"modelPath"`
// }

// func InitViperForEtcdRemote() error {
// 	viper.SetConfigType("yaml")
// 	err := viper.AddRemoteProvider("etcd3", "http://10.1.6.48:31927", "/wecho")
// 	if err != nil {
// 		panic(err)
// 	}
// 	err = viper.ReadRemoteConfig()
// 	if err != nil {
// 		panic(err)
// 	}
// 	// 配置信息反序列化
// 	if err := viper.Unmarshal(Conf); err != nil {
// 		panic(err)
// 	}
// 	// 开始监听配置文件
// 	viper.WatchConfig()
// 	// 这个地方只能告诉你配置文件发生了变化，重新加载配置信息
// 	viper.OnConfigChange(func(in fsnotify.Event) {
// 		zap.S().Debugf("config file changed: %s", in.Name)
// 		if err := viper.Unmarshal(Conf); err != nil {
// 			panic(err)
// 		}
// 	})
// 	return nil
// }

// ValidateConfig 验证配置项的有效性
func ValidateConfig() error {
	if Conf.Port < 1024 || Conf.Port > 65535 {
		return cfmt.Errorf("{{port must be between 1024 and 65535}}::red")

	}

	if Conf.Mode != "dev" && Conf.Mode != "prod" {
		return cfmt.Errorf("{{mode must be either 'dev' or 'prod'}}::red")
	}

	if Conf.MySQLConfig.Host == "" {
		return cfmt.Errorf("{{mysql host cannot be empty}}::red")
	}
	fmt.Println(Conf.LogConfig.Filename)
	if Conf.LogConfig.Filename == "" {
		return cfmt.Errorf("{{log filename cannot be empty}}::red")
	}

	return nil
}

// InitialConfiguration 初始化Viper配置信息
func InitialConfiguration() error {
	v := viper.New()
	v.SetConfigName("config-test")
	v.SetConfigType("yaml")
	v.AddConfigPath("./config")

	// 支持环境变量
	v.AutomaticEnv()
	v.SetEnvPrefix("WECHO")
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

	// 读取配置文件
	if err := v.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
			return err
		}
	}

	// 配置信息反序列化
	if err := v.Unmarshal(Conf); err != nil {
		return err
	}

	// 验证配置项
	if err := ValidateConfig(); err != nil {
		return err
	}

	// 开始监听配置文件
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		zap.S().Debugf("config file changed: %s", in.Name)
		if err := v.Unmarshal(Conf); err != nil {
			zap.S().Errorf("failed to reload config: %v", err)
		}
	})
	return nil
}
